import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;


public class Stub_Generateur {
	
	// main pour tester uniquement
	/*public static void main(String[] args) {
		try {
			generer(Class.forName(args[0]));
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}*/

	public static SharedObject generer(Class classe, int id, Object o){
		
		String texte="";		
			
		String nomInterface ="";
		String nomClasse ="";		
		if(classe.isInterface()){
			nomInterface = classe.getSimpleName();		
			nomClasse = nomInterface.substring(0, nomInterface.length() - "_itf".length());	
		}
		else {
			nomClasse = classe.getSimpleName();		
			nomInterface = nomClasse + "_itf";
		}
		String nomStub= nomClasse + "_stub";
		
		texte += "public class " + nomStub  + " extends SharedObject implements " + nomInterface + ", java.io.Serializable {";
		texte += " \n\n";	
		
		/** constructeur **/		
		texte += "\tpublic " + nomStub + "(int id, Object o) {" ;
		texte += " \n\t\t";
		texte += "super(id,o);";
		texte += "\n\t";
		texte += "}";
		texte += "\n\n";
		
		
		for( Method m : classe.getDeclaredMethods()){			
			
			// Recherche arguments
			int cpt =0;
			String listeArguments ="";
			String listeNomArguments="";
			for(Class paramTypes : m.getParameterTypes() ){
				if(cpt>0){
					listeArguments += ", ";
					listeNomArguments += ", ";
				}
				listeArguments += paramTypes.getSimpleName() +" arg" + cpt;
				listeNomArguments += "arg" + cpt;
				cpt++;
			}
			
			texte += "\tpublic " + m.getReturnType().getSimpleName() + " " + m.getName() + "(" + listeArguments +") {" ;
			texte += " \n\t\t";	
			
			texte += nomClasse + " x = (" + nomClasse + ") obj;";
			texte += "\n\t\t";			
			
			if( ! m.getReturnType().getSimpleName().equals("void") ){
				texte += "return ";
			}
			
			texte += "x." + m.getName() + "(" + listeNomArguments +");";
			texte += "\n\t";	
			
			texte += "}";
			texte += "\n\n";	
		}
		
		texte += "}";
		
		// Creation du fichier
		File f = new File(nomStub +".java");
		try {
			f.createNewFile();
			FileOutputStream fileOS = new FileOutputStream(f);		
			fileOS.write(texte.getBytes());
		} catch (IOException e) {
			e.printStackTrace();
		}		
		
		
		//Compilation
        File f2 = new File(nomStub +".java");
        try{
	        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
	        StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
	        Iterable ite = fileManager.getJavaFileObjects(f);
	        compiler.getTask(null, fileManager, null, null,null, ite).call();
	        fileManager.close();
        }catch (Exception e){
        	e.printStackTrace();
        }
        
        //Instantiation du stub
		Class<?> classeStub;
		SharedObject sho =null;
		try {
			classeStub = Class.forName(nomStub);
			java.lang.reflect.Constructor<?> constructeur = classeStub.getConstructor(new Class[] { int.class, Object.class }); 
			sho = (SharedObject) constructeur.newInstance(new Object[] { id, o }); 
		} catch (Exception e) {
			e.printStackTrace();
		}		 		
		return sho;

	}
}
